﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestGUISystem
{
         //
         //包传输的结构如下：
         //  主发送: 2字节包头  地址 1   命令 1    子命令 1        数据长度 2   数据n   校验 1  包尾 2  
         //          0xaa55      1-31    1          1                                           0x5aa5
         // 从回应 ：2字节包头  地址 1   命令 1   命令执行状态 1   数据长度 2   数据n   校验 1  包尾 2 
    //               0xaa55      1-31    1          1                                           0x5aa5
         // 
         // 
         // 
         //
    public enum CommandStatus //定义命令执行的状态
    {
        ExeSucessful,
        ExeError
    }



    /// <summary>
    /// 此类用于无线传输数据包的打包或者解包
    /// </summary>
    public class PackUppackClass
    {
       
        #region 私有变量区

        private byte[] _packBuffer = new byte[512];
        private byte[] _unpackBuffer = new byte[512];

        #endregion

        #region 属性区

        public byte[] PackBuffer 
        {
            get{return _packBuffer;}
            set
            {
                _packBuffer=value;
            }
        }
        public int PackDataLength{private set;get;}

        public byte[] UnpackBuffer
        {
            get 
            {
                return _unpackBuffer;
            }
            private set 
            {
                _unpackBuffer=value;
            }
        }
        public int UnpackDataLength
        {
            get;
            private set;
        }

        public byte Address {private set; get; }
        public byte Command { private set; get; }
        public byte CommandState { private set; get; }


        #endregion

        #region 方法

        /// <summary>
        /// 打包数据
        /// </summary>
        /// <param name="TVAddress">地址</param>
        /// <param name="cmdStr">数据</param>
        void PKCommandToBuffer(int TVAddress, string cmdStr)
        {
            byte[] temp_buffer = new byte[200];

            for (int i = 0; i < cmdStr.Length; i++)
            {
                temp_buffer[i] = Convert.ToByte(cmdStr[i]);
            }
            SetupPackData(TVAddress, 1, 1, temp_buffer, cmdStr.Length);
        }

        /// <summary>
        /// 将数据打包
        /// </summary>
        /// <param name="addr">地址</param>
        /// <param name="cmd">命令</param>
        /// <param name="subcom">子命令</param>
        /// <param name="data_in">数据</param>
        /// <param name="data_len">数据长度</param>
        public void SetupPackData(int addr, int cmd, int subcom, byte[] data_in, int data_len)
        {
            PackBuffer[0] = 0xaa; //指令开头第1字节
            PackBuffer[1] = 0x55; //指令开头第2字节
            PackBuffer[2] = (byte)addr;
            PackBuffer[3] = (byte)cmd;
            PackBuffer[4] = (byte)subcom;
            PackBuffer[5] = (byte)(data_len / 256);
            PackBuffer[6] = (byte)(data_len & 0xff);
            for (int i = 0; i < data_len; i++)
            {
                PackBuffer[7 + i] = data_in[i];
            }
            int k = 7 + data_len;
            byte check = 0;
            for (int j = 2; j < k; j++)
            {
                check ^= PackBuffer[j];//异或
            }
            PackBuffer[k] = check;
            PackBuffer[k + 1] = 0x5a;//指令结尾第1字节
            PackBuffer[k + 2] = 0xa5;//指令结尾第2字节
            PackDataLength = k + 3;
        }
        /// <summary>
        /// 将解包的一些属性恢复为默认值
        /// </summary>
        private void DefaultUnpackData()
        {
            UnpackDataLength = 0;
            Address = 0;
            Command = 0;
            CommandState = 0;
        }


        /// <summary>
        /// 解包输入的数据，查看是否有包的存在
        /// </summary>
        /// <param name="data_list"></param>
        /// <param name="data_len"></param>
        /// <returns></returns>
        public bool CheckUnpackData(byte[] data_list, int data_len)
        {
            bool ret = false;
            int start = 0;
            int end = 0;
            bool f_s = false;
            bool f_e = false;
            int data_start;

            DefaultUnpackData();
            //检测是否有包头
            int i;
            for (i = 0; i < data_len; i++)
            {
                if (data_list[i] == 0x55 && i != 0 && data_list[i - 1] == 0xaa)//检测到包头
                {
                    f_s = true;
                    start=i+1;
                    break;
                }
            }
            if(i>=data_len) return false;
            //找包尾
            for (i = start; i < data_len; i++)
            {
                if (i != 0 && data_list[i] == 0xa5 && data_list[i - 1] == 0x5a)//结束标志
                {
                    f_e = true;
                    end = i-2;
                }
            }
            if (i >= data_len) return false;

            //checksum
            byte check = 0;
            for (i = start; i < end; i++)
            {
                check ^= data_list[i];
            }
            if (check != data_list[end]) return false;//校验和不符

            //解包正确，获取包中的数据
            this.Address = data_list[start];
            this.Command = data_list[start + 1];
            this.CommandState = data_list[start + 2];
            //
            this.UnpackDataLength = data_list[start + 3] * 256 + data_list[start + 4];
            for (i = 0; i < UnpackDataLength; i++)
            {
                UnpackBuffer[i] = data_list[start + 5 + i];
            }

            ret = true;

            return ret;
        }

        #endregion
    }
}
